﻿using System;
using System.Threading;

namespace RG.Common
{
    public static class ExecInSta
    {
        /// <summary>
        /// Выполняет код в окружении Single-Thread Apartment
        /// </summary>
        public static TResult Do<TArgs, TResult>(TArgs args, Func<TArgs, TResult> func)
        {
            var worker = new Worker<TArgs, TResult> {func = func, args = args};
            var t = new Thread(worker.go);
            t.SetApartmentState(ApartmentState.STA);
            t.Start();
            t.Join();
            if (worker.ex != null) throw worker.ex;
            return worker.result;
        }

        public static TResult Do<TResult>(Func<TResult> func)
        {
            return Do(0, x => func());
        }

        class Worker<TArgs, TResult>
        {
            public Func<TArgs, TResult> func;
            public TArgs args;
            public TResult result;
            public Exception ex;

            public void go()
            {
                try
                {
                    result = func(args);
                }
                catch (Exception ee)
                {
                    ex = ee;
                }
            }
        }
    }
}
